﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

using JetBrains.Annotations;

using WpfApp4.Models;
using WpfApp4.Models.Config;
using WpfApp4.Utilities;

using XEvent;
using XEvent.Events;
using XEvent.UI;

namespace WpfApp4.ViewModels
{
    public class NewSettingWindowViewModel : ViewModelBase
    {
        private WindowEvent _windowEvent;

        public NewSettingWindowViewModel()
        {
            _windowEvent = XEventAgent.Instance.EventManager.GetEvent<WindowEvent>();

            TheNewVisible = Visibility.Collapsed;
            DTOConvert();
            SelectedMenu = Root;
            SettingCfg = MenuInfo.Instance.Settings;
            Init();
        }

        #region Commands

        public ICommand AddMenuCommand
        {
            get => new RelayCommand<object>(obj =>
            {
                TheNewVisible = Visibility.Visible;
                NewMenu = new MenuConfigDTO();
                CurrentMenu = SelectedMenu;
            });
        }

        public ICommand SubmitCommand
        {
            get => new RelayCommand<object>(obj =>
            {
                try
                {
                    if (string.IsNullOrWhiteSpace(NewMenu.Name)) return;
                    SelectedMenu = CurrentMenu;
                    CurrentMenu = null;

                    NewMenu.Parent = SelectedMenu;
                    SelectedMenu.MenuItems.Add(NewMenu);
                    TheNewVisible = Visibility.Collapsed;
                }
                catch
                {

                }
            });
        }

        public ICommand CancelCommand
        {
            get => new RelayCommand<object>(obj =>
            {
                TheNewVisible = Visibility.Collapsed;
            });
        }

        public ICommand SaveCommand
        {
            get => new RelayCommand<object>(obj =>
            {
                DTOConvertBack();
                MenuInfo.Instance.Settings = SettingCfg;
                ConfigManager.SaveConfig();

                _windowEvent.Publish(new WindowEvent
                {
                    Type = EventType.Action,
                    WindowActionType = WindowActionType.Close,
                    EventId = EventId.NewMenuSettingWindow,
                });
            });
        }

        public ICommand DeleteMenuCommand
        {
            get => new RelayCommand<object>(obj =>
            {
                if (SelectedMenu.Parent != null)
                {
                    var parent = SelectedMenu.Parent;
                    parent.MenuItems.Remove(SelectedMenu);
                    SelectedMenu = null;
                }
            });
        }

        public ICommand MoveIndexCommand
        {
            get => new RelayCommand<string>(dir =>
            {
                switch (dir)
                {
                    case "Up":
                        MoveUp();
                        break;
                    case "Down":
                        MoveDown();
                        break;
                    case "Top":
                        MoveTop();
                        break;
                }
            });
        }



        #endregion


        #region Property

        private MenuConfigDTO _root;
        public MenuConfigDTO Root { get => _root; set => SetProperty(ref _root, value); }


        private MenuConfigDTO _currentMenu;
        public MenuConfigDTO CurrentMenu { get => _currentMenu; set => SetProperty(ref _currentMenu, value); }


        private MenuConfigDTO _selectedMenu;
        public MenuConfigDTO SelectedMenu { get => _selectedMenu; set => SetProperty(ref _selectedMenu, value); }


        private MenuConfigDTO _newMenu;
        public MenuConfigDTO NewMenu { get => _newMenu; set => SetProperty(ref _newMenu, value); }

        private SettingConfig _settingCfg;
        public SettingConfig SettingCfg { get => _settingCfg; set => SetProperty(ref _settingCfg, value); }


        private Visibility _theNewVisible;
        public Visibility TheNewVisible { get => _theNewVisible; set => SetProperty(ref _theNewVisible, value); }


        public ObservableCollection<OpenModel> OpenModelCollection { get; private set; } = new ObservableCollection<OpenModel>();

        public ObservableCollection<string> CommandCollection { get; private set; } = new ObservableCollection<string>();

        #endregion


        #region Functions

        private void Init()
        {
            OpenModelCollection.Add(OpenModel.CurrentWindow);
            OpenModelCollection.Add(OpenModel.NewWindow);

            CommandCollection.Add("");
            CommandCollection.Add("OpenUrlCommand");
            CommandCollection.Add("OpenUrlInputCommand");
            CommandCollection.Add("SearchCommand");
            CommandCollection.Add("CloseBrowserWindowCommand");
            CommandCollection.Add("RefreshMenuCommand");
            CommandCollection.Add("OpenWindowCommand");
            CommandCollection.Add("ExitAppCommand");
            CommandCollection.Add("OpenConfigCommand");
            CommandCollection.Add("OpenFileByVSCodeCommand");
            CommandCollection.Add("OpenFileCommand");
            CommandCollection.Add("UpdateWindowSizeCommand");
            CommandCollection.Add("SetWallpaperCommand");
            CommandCollection.Add("ApplyWallpaper");
            CommandCollection.Add("SettingWallpaperCommand");
            CommandCollection.Add("ExitWallpaperCommand");
            CommandCollection.Add("OpenApplicationCommand");
            CommandCollection.Add("StartProcessCommand");
            CommandCollection.Add("ExitProcessCommand");
        }

        private void MoveUp()
        {
            if (SelectedMenu.Parent != null)
            {
                var parent = SelectedMenu.Parent;
                var node = SelectedMenu.Clone();
                node.Parent = parent;

                var index = parent.MenuItems.IndexOf(SelectedMenu);
                if (index == 0) return;

                parent.MenuItems.RemoveAt(index);
                index--;
                parent.MenuItems.Insert(index, node);
            }
        }

        private void MoveDown()
        {
            if (SelectedMenu.Parent != null)
            {
                var parent = SelectedMenu.Parent;
                var node = SelectedMenu.Clone();
                node.Parent = parent;

                var index = parent.MenuItems.IndexOf(SelectedMenu);
                if (index == parent.MenuItems.Count - 1) return;

                parent.MenuItems.RemoveAt(index);
                index++;
                parent.MenuItems.Insert(index, node);
            }
        }

        private void MoveTop()
        {
            if (SelectedMenu.Parent != null)
            {
                var parent = SelectedMenu.Parent;
                var node = SelectedMenu.Clone();
                node.Parent = parent;

                var index = parent.MenuItems.IndexOf(SelectedMenu);
                if (index == 0) return;

                parent.MenuItems.RemoveAt(index);
                parent.MenuItems.Insert(0, node);
            }
        }

        public void SelectedChangedEvent(object value)
        {
            if (value is MenuConfigDTO selected)
            {
                SelectedMenu = selected;
            }
        }


        private void DTOConvert()
        {
            Root = new MenuConfigDTO();
            var menuItems = MenuInfo.Instance.MenuItems;
            LoadMenu(Root, menuItems);
        }

        private void DTOConvertBack()
        {
            var menuItems = new List<MenuConfig>();
            LoadDTO(menuItems, Root.MenuItems);
            MenuInfo.Instance.MenuItems = menuItems.ToArray();
        }

        private void LoadMenu(MenuConfigDTO parent, MenuConfig[] menuItems)
        {
            foreach (var item in menuItems)
            {
                var menuDto = new MenuConfigDTO
                {
                    Id = item.Id,
                    Name = item.Name,
                    Command = item.Command,
                    CommandParameter = item.CommandParameter,
                    WindowSize = item.WindowSize,
                    OpenModel = item.OpenModel,
                    MenuItems = new ObservableCollection<MenuConfigDTO>(),
                };

                if (item.MenuItems != null && item.MenuItems.Length > 0)
                {
                    LoadMenu(menuDto, item.MenuItems);
                }
                menuDto.Parent = parent;
                parent.MenuItems.Add(menuDto);
            }
        }

        private void LoadDTO(List<MenuConfig> list, ObservableCollection<MenuConfigDTO> menuItems)
        {
            foreach (var item in menuItems)
            {
                var menu = new MenuConfig
                {
                    Id = item.Id,
                    Name = item.Name,
                    Command = item.Command,
                    CommandParameter = item.CommandParameter,
                    OpenModel = item.OpenModel,
                    WindowSize = item.WindowSize,
                };
                if (item.MenuItems != null && item.MenuItems.Count > 0)
                {
                    var mi = new List<MenuConfig>();
                    LoadDTO(mi, item.MenuItems);
                    menu.MenuItems = mi.ToArray();
                }
                list.Add(menu);
            }
        }

        #endregion
    }
}
